package com.zerocarbon.framework.common.result;

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.zerocarbon.framework.common.enums.BaseExceptionCode;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

/**
 * 接口请求响应返回对象
 * @author wyf
 * @date 2020年3月5日 
 * @param <T>
 */
@Getter
@Setter
@SuppressWarnings("unused")
@Accessors(chain = true)
public class Result<T> implements Serializable {
	
	private static final long serialVersionUID = -8106037616634398108L;
	public static final String DEF_ERROR_MESSAGE = "系统繁忙，请稍候再试";
	public static final String HYSTRIX_ERROR_MESSAGE = "请求超时，请稍候再试";
	public static final int SUCCESS_CODE = 0;					//成功
	public static final int FAIL_CODE = 1;						//系统繁忙
	public static final int TIMEOUT_CODE = 2;					//超时
	
	public static final int OPERATION_EX_CODE = 10;				//接口返回失败
    public static final int VALID_EX_CODE = 9;					//统一参数验证异常

    private int code;											//调用是否成功标识，0：成功，-1:系统繁忙，此时请开发者稍候再试 详情见[ExceptionCode]
    
    @JsonIgnore
    private Boolean defExec = true;								//是否执行默认操作

	@JsonSerialize(include= JsonSerialize.Inclusion.ALWAYS)  //为空不序列化参数
    private T data;												//调用结果

    private String message;										//结果消息，如果调用成功，消息通常为空T

    //@ApiModelProperty(value = "请求路径")
    //private String path;										//
    
    private Map<String, Object> extra;							//附加数据

    private long timestamp = System.currentTimeMillis();		//响应时间

	private Result() {
        super();
    }

    public Result(int code, T data, String msg) {
        this.code = code;
        this.data = data;
        this.message = msg;
        this.defExec = false;
    }
    
    public Result(int code, T data, String message, boolean defExec) {
        this.code = code;
        this.data = data;
        this.message = message;
        this.defExec = defExec;
    }

    /**
     * 响应结果
     * @param code
     * @param data
     * @param msg
     * @return
     */
    public static <E> Result<E> result(int code, E data, String msg) {
        return new Result<>(code, data, msg);
    }
    
    public static <E> Result<E> success(int code, E data, String msg) {
        return new Result<>(code, data, msg);
    }

    public static <E> Result<E> success(E data) {
        return new Result<>(SUCCESS_CODE, data, null);
    }

    public static Result<Boolean> success() {
        return new Result<>(SUCCESS_CODE, true, null);
    }

    public static <E> Result<E> success(E data, String msg) {
        return new Result<>(SUCCESS_CODE, data, msg);
    }
    
    public static <E> Result<E> successDef(E data) {
        return new Result<>(SUCCESS_CODE, data, "ok", true);
    }

    public static <E> Result<E> successDef() {
        return new Result<>(SUCCESS_CODE, null, "ok", true);
    }

    public static <E> Result<E> successDef(E data, String msg) {
        return new Result<>(SUCCESS_CODE, data, msg, true);
    }

    /**
     * 请求失败消息
     * @param code
     * @param msg
     * @return
     */
    public static <E> Result<E> fail(int code, String msg) {
        return new Result<>(code, null, (msg == null || msg.isEmpty()) ? DEF_ERROR_MESSAGE : msg);
    }

    public static <E> Result<E> fail(String msg) {
        return fail(OPERATION_EX_CODE, msg);
    }

    public static <E> Result<E> fail(String msg, Object... args) {
        String message = (msg == null || msg.isEmpty()) ? DEF_ERROR_MESSAGE : msg;
        return new Result<>(OPERATION_EX_CODE, null, String.format(message, args));
    }

    public static <E> Result<E> fail(BaseExceptionCode exceptionCode) {
        return failValid(exceptionCode);
    }
    
    /*public static <E> Result<E> fail(BizException exception) {
        if (exception == null) {
            return fail(DEF_ERROR_MESSAGE);
        }
        return new R<>(exception.getCode(), null, exception.getMessage());
    }*/

    /**
     * 请求失败消息，根据异常类型，获取不同的提供消息
     * @param throwable 异常
     * @return RPC调用结果
     */
    public static <E> Result<E> fail(Throwable throwable) {
        return fail(FAIL_CODE, throwable != null ? throwable.getMessage() : DEF_ERROR_MESSAGE);
    }
    
    public static <E> Result<E> timeout() {
        return fail(TIMEOUT_CODE, HYSTRIX_ERROR_MESSAGE);
    }

    /**
     * 验证失败
     * @param msg
     * @return
     */
    public static <E> Result<E> failValid(String msg) {
        return new Result<>(VALID_EX_CODE, null, (msg == null || msg.isEmpty()) ? DEF_ERROR_MESSAGE : msg);
    }

    public static <E> Result<E> failValid(String msg, Object... args) {
        String message = (msg == null || msg.isEmpty()) ? DEF_ERROR_MESSAGE : msg;
        return new Result<>(VALID_EX_CODE, null, String.format(message, args));
    }

    public static <E> Result<E> failValid(BaseExceptionCode exceptionCode) {
        return new Result<>(exceptionCode.getCode(), null, (exceptionCode.getMessage() == null || exceptionCode.getMessage().isEmpty()) ? DEF_ERROR_MESSAGE : exceptionCode.getMessage());
    }

    public static <E> Result<E> failTimeout() {
        return fail(TIMEOUT_CODE, HYSTRIX_ERROR_MESSAGE);
    }

    public Result<T> put(String key, Object value) {
        if (this.extra == null) {
            this.extra = new HashMap<>(10);
        }
        this.extra.put(key, value);
        return this;
    }

    /**
     * 逻辑处理是否成功
     * @return 是否成功
     */
    public Boolean getIsSuccess() {
        return this.code == SUCCESS_CODE || this.code == 200;
    }

    @Override
    public String toString() {
        return JSONObject.toJSONString(this);
    }
}
